﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using JSON;
using Facebook_Graph_Toolkit.FacebookObjects;

namespace Facebook_Graph_Toolkit.GraphApi {
    /// <summary>
    /// represents a Facebook User
    /// </summary>
    [Serializable]
    public class User : GraphApiObject{
        internal User(JsonObject JO) : base(JO) {
        }
        #region Constructors
        /// <summary>
        /// Gets the general information of a Facebook User. For detailed information, pass the AccessToken in a overloaded of this constructor.
        /// </summary>
        /// <param name="UserID">User ID</param>
        public User(string UserID) : base (Helpers.WebResponseHelper.GetJsonFromFacebookObject(UserID, null)){
        }
        /// <summary>
        /// Gets the information of a Facebook User.
        /// </summary>
        /// <param name="UserID">User ID</param>
        /// <param name="AccessToken">Access Token</param>
        public User(string UserID, string AccessToken) : base (Helpers.WebResponseHelper.GetJsonFromFacebookObject(UserID, AccessToken)){
        }
        #endregion

        #region Public Properties
        /// <summary>
        /// The user's Facebook ID
        /// </summary>
        public string ID { get { return (string)data["id"];  }  }
        /// <summary>
        /// The user's full name
        /// </summary>
        public string Name {  get { return (string)data["name"];  }  }
        /// <summary>
        /// The user's first name
        /// </summary>
        public string FirstName { get { return (string)data["first_name"];  }  }
        /// <summary>
        /// The user's middle name
        /// </summary>
        public string MiddleName { get { return (string)data["middle_name"]; } }
        /// <summary>
        /// The user's last name
        /// </summary>
        public string LastName {  get {  return (string)data["last_name"];  }  }
        /// <summary>
        /// The user's username
        /// </summary>
        public string Username { get { return (string)data["username"]; } }
        /// <summary>
        /// The URL of the profile for the user on Facebook
        /// </summary>
        public string NavigateUrl { get {  return (string)data["link"];   }    }
        /// <summary>
        /// The user's gender
        /// </summary>
        public string Gender {  get {  return (string)data["gender"];  }  }
        /// <summary>
        /// The proxied or contact email address granted by the user
        /// </summary>
        public string Email { get { return (string)data["email"]; } }
        /// <summary>
        /// The user's timezone offset from UTC
        /// </summary>
        public int? Timezone {  get { return (int?)data["timezone"];   }    }
        /// <summary>
        /// The user's locale
        /// </summary>
        public string Locale { get {  return (string)data["locale"];   }    }
        /// <summary>
        /// The user's account verification status
        /// </summary>
        public bool? Verified {
            get {
                return (bool?)data["verified"];
            }
        }
        /// <summary>
        /// The last time the user's profile was updated
        /// </summary>
        public DateTime? UpdatedTime {
            get {
                if (data["updated_time"] == null) return null;
                return Helpers.Common.RFC3339ToDateTime((string)data["updated_time"]);
            }
        }
        /// <summary>
        /// The user's biography
        /// </summary>
        public string Biography { get { return (string)data["bio"]; } }
        /// <summary>
        /// The user's birthday
        /// </summary>
        public DateTime? Birthday {
            get {
                if (data["birthday"] == null) return null;
                return Convert.ToDateTime(data["birthday"].ToString());
            }
        }
        /// <summary>
        /// The user's current location
        /// </summary>
        public NameIDPair Location {
            get {
                if (data["location"] == null) return null;
                return new NameIDPair(new JsonObject(data["location"].ToString()));
            }
        }
        /// <summary>
        /// The user's hometown
        /// </summary>
        public NameIDPair Hometown {
            get {
                if (data["hometown"] == null) return null;
                return new NameIDPair(new JsonObject(data["hometown"].ToString()));
            }
        }
        /// <summary>
        /// The user's languages
        /// </summary>
        public IList<NameIDPair> Languages {
            get {
                if (data["languages"] == null) return null;
                JsonArray JA = new JsonArray(data["languages"].ToString());
                IList<NameIDPair> languages = new List<NameIDPair>();
                foreach (JsonObject JO in JA) languages.Add(new NameIDPair(JO));
                return languages;
            }
        }
        /// <summary>
        /// The user's relationship status
        /// </summary>
        public Relationship? RelationshipStatus {
            get {
                if (data["relationship_status"] == null) return null;
                switch (data["relationship_status"].ToString()) {
                    case "Single": return Relationship.Single;
                    case "In a relationship": return Relationship.InRelationship;
                    case "Engaged": return Relationship.Engaged;
                    case "Married": return Relationship.Married;
                    case "It's complicated": return Relationship.Complicated;
                    case "In an open relationship": return Relationship.Open;
                    case "Widowed": return Relationship.Widowed;
                    case "Separated": return Relationship.Separated;
                    case "Divorced": return Relationship.Divorced;
                    default:
                        throw new FacebookException("Unknown relationship: " + data["relationship_status"].ToString()+". Cannot implement enumeration.");
                }
            }
        }
        /// <summary>
        /// The user's political view
        /// </summary>
        public string PoliticalView { get { return (string)data["political"]; } }
        /// <summary>
        /// The user's religion
        /// </summary>
        public string Religion { get { return (string)data["religion"]; } }
        #endregion

        #region connections
        /// <summary>
        /// Gets all Photo Albums of a user
        /// </summary>
        /// <param name="AccessToken">Access Token</param>
        /// <param name="UserID">User ID</param>
        /// <param name="Limit">Maximum number of albums returned</param>
        /// <param name="Offset">Number of albums to offset before returning the first album</param>
        /// <returns>The albums that belong to the user</returns>
        public static IList<Album> GetAlbums(string UserID, string AccessToken, int? Offset, int? Limit) {
            return Helpers.ApiCaller.GetAlbums(UserID, AccessToken, Offset, Limit);
        }

        /// <summary>
        /// Gets the wall of a user
        /// </summary>
        /// <param name="AccessToken">Access Token</param>
        /// <param name="UserID">User ID</param>
        /// <param name="Limit">Maximum number of posts returned</param>
        /// <param name="Offset">Number of posts to offset before returning the first post</param>
        /// <returns>The user's wall</returns>
        public static IList<Post> GetFeed(string UserID, string AccessToken,int? Offset, int? Limit) {
            return Helpers.ApiCaller.GetFeed(UserID, AccessToken, Offset, Limit);
        }

        /// <summary>
        /// Gets posts by a user
        /// </summary>
        /// <param name="AccessToken">Access Token</param>
        /// <param name="UserID">User ID</param>
        /// <param name="Offset">The number of posts to offset before the first returned post</param>
        /// <param name="Limit">The maximum number of posts returned</param>
        /// <returns>The user's own posts</returns>
        public static IList<Post> GetPosts(string UserID, string AccessToken, int? Offset, int? Limit) {
            return Helpers.ApiCaller.GetPosts(UserID, AccessToken, Offset, Limit);
        }

        /// <summary>
        /// Gets the feeds that are seen by the user on the homepage
        /// </summary>
        /// <param name="AccessToken">Access Token</param>
        /// <param name="UserID">User ID</param>
        /// <param name="Offset">The number of posts to offset before the first returned post</param>
        /// <param name="Limit">The maximum number of posts returned</param>
        /// <returns>The feeds on the user's homepage</returns>
        public static IList<Post> GetHome(string UserID, string AccessToken, int? Offset, int? Limit) {
            return Helpers.ApiCaller.GetHome(UserID, AccessToken, Offset, Limit);
        }

        /// <summary>
        /// Gets the links posted by the current user
        /// </summary>
        /// <param name="AccessToken">Access Token</param>
        /// <param name="UserID">User ID</param>
        /// <param name="Limit">Maximum number of links returned</param>
        /// <param name="Offset">Number of links to offset before returning the first link</param>
        /// <returns>The user's posted links</returns>
        public static IList<Link> GetLinks(string UserID, string AccessToken, int? Offset, int? Limit) {
            return Helpers.ApiCaller.GetLinks(UserID, AccessToken, Offset, Limit);
        }

        /// <summary>
        /// Gets the friends of the user
        /// </summary>
        /// <param name="AccessToken">Access Token</param>
        /// <param name="UserID">User ID</param>
        /// <param name="Limit">Maxinum number of friends returned</param>
        /// <param name="Offset">Number of friends to skip before returning the first friend</param>
        /// <returns>The user's friends</returns>
        public static IList<NameIDPair> GetFriends(string UserID, string AccessToken, int? Offset, int? Limit) {
            return Helpers.ApiCaller.GetFriends(UserID, AccessToken, Offset,Limit);
        }

        /// <summary>
        /// Gets the user's status updates
        /// </summary>
        /// <param name="AccessToken">Access Token</param>
        /// <param name="UserID">User ID</param>
        /// <param name="Limit">Maximum number of status messages returned</param>
        /// <param name="Offset">Number of status messages to offset before returning the first status message</param>
        /// <returns>The user's status updates</returns>
        public static IList<StatusMessage> GetStatusMessages(string UserID, string AccessToken, int? Offset, int? Limit) {
            return Helpers.ApiCaller.GetStatusMessages(UserID, AccessToken, Offset, Limit);
        }

        /// <summary>
        /// Gets the notes of a particular user
        /// </summary>
        /// <param name="UserID">User ID</param>
        /// <param name="AccessToken">Access Token</param>
        /// <param name="Limit">Maximum number of Notes returned</param>
        /// <param name="Offset">Number of Notes to skip before returning the first Note</param>
        /// <returns></returns>
        public static IList<Note> GetNotes(string UserID, string AccessToken, int? Offset, int? Limit) {
            return Helpers.ApiCaller.GetNotes(UserID, AccessToken, Offset, Limit);
        }

        /// <summary>
        /// Gets all the Pages the user has liked
        /// </summary>
        /// <param name="AccessToken">Access Token</param>
        /// <param name="UserID">User ID</param>
        /// <param name="Limit">Maximum number of Pages returned</param>
        /// <param name="Offset">Number of Pages to skip before returning the first Page</param>
        /// <returns>All the Pages the user has liked</returns>
        public static IList<LikedPage> GetLikedPages(string UserID, string AccessToken, int? Offset, int? Limit) {
            return Helpers.ApiCaller.GetLikedPages(UserID, AccessToken,Offset,Limit);
        }

        /// <summary>
        /// Gets the Groups that the user has joined
        /// </summary>
        /// <param name="AccessToken">Access Token</param>
        /// <param name="UserID">User ID</param>
        /// <param name="Limit">Maximum number of Groups returned</param>
        /// <param name="Offset">Number of Groups to skip before returning the first Group</param>
        /// <returns>The groups the user is a member of</returns>
        public static IList<GroupBookmark> GetGroups(string UserID, string AccessToken, int? Offset, int? Limit) {
            return Helpers.ApiCaller.GetGroups(UserID, AccessToken,Offset,Limit);
        }

        /// <summary>
        /// Gets the events the user is or maybe attending
        /// </summary>
        /// <param name="AccessToken">Access Token</param>
        /// <param name="UserID">User ID</param>
        /// <param name="Limit">Maximum number of Events returned</param>
        /// <param name="Offset">Number of Events to skip before returning the first Event</param>
        /// <returns>The events the user is or maybe attending</returns>
        public static IList<UserEvent> GetEvents(string UserID, string AccessToken,int? Offset, int? Limit) {
            return Helpers.ApiCaller.GetEvents(UserID, AccessToken,Offset,Limit);
        }
        /// <summary>
        /// Gets the notifications of the user
        /// </summary>
        /// <param name="UserID">User ID</param>
        /// <param name="AccessToken">Access Token</param>
        /// <param name="Offset">Number of Notifications to skip before returning the first record</param>
        /// <param name="Limit">Maximum number of Notifications returned</param>
        /// <param name="UnreadOnly">Whether to only return Notifications that are unread by the user</param>
        /// <returns>The user's notifications</returns>
        public static IList<Notification> GetNotifications(string UserID, string AccessToken, int? Offset, int? Limit, bool UnreadOnly) {
            return Helpers.ApiCaller.GetNotifications(UserID, AccessToken, Offset, Limit, UnreadOnly);
        }

        #endregion
    }
}
